断言在Java良好实践中主动抛出断言错误?
翻阅Joshua Bloch的“有效Java-第二版”,我在第152页偶然发现了以下代码:
double apply(double x, double y) {
switch(this) {
case PLUS: return x + y;
case MINUS: return x - y;
case TIMES: return x * y;
case DIVIDE: return x / y;
}
throw new AssertionError("Unknown op: " + this);
}
现在让我困惑的是,AssertionError
被主动抛出。这算是好的做法吗?
据我所知,断言用于不干扰代码,因此当java编程在未启用断言的情况下启动时,因此不会执行断言语句,行为不会改变。
如果我在运行程序时甚至没有启用断言,就会得到一个AssertionException
,我会感到相当困惑
尽管我知道示例案例可能经常发生,但您分析了几个不同的选项,如果没有,您应该抛出一个异常
那么,在这里抛出一个AssertionException
是一个好的做法,还是抛出一个不同的更好?如果是,哪一个最合适?也许IllegalArgumentException
编辑澄清:我的问题不是我们是否应该在这里抛出Error
,而是如果我们想抛出Exception
或Error
,应该是哪一个?积极抛出AssertionError
是一种良好的做法吗?文档中说抛出表示断言失败,所以我觉得我们不应该主动抛出它。对吗
第二次编辑:明确的问题:积极抛出AssertionError
是一种良好的做法,还是应该避免,即使这是可能的?(我猜读文件是后者)
# 1 楼答案
我宁愿
AssertionError
,因为它应该为实际断言保留李>但我更喜欢https://stackoverflow.com/a/41324246/348975
# 2 楼答案
我认为无论是断言者还是非法者在这里都不是很好。断言错误不符合Matt的回答。这里的参数没有错,它们只是在错误的
this
操作中传递给了一个方法。因此,IAE可能也不太好。当然,这也是一个基于意见的问答另外,我不确定启用断言对于抛出AssertionError是强制性的,或者AssertionError表示启用了断言
# 3 楼答案
据我所知,您的方法是枚举对象的方法。在大多数情况下,当有人添加新的枚举值时,他也应该修改“apply”方法。在这种情况下,您应该抛出UnsupportedOperationException
# 4 楼答案
我同意布洛赫先生的看法——备选方案(
IllegalArgumentException
、IllegalStateException
和UnsupportedOperationException
)没有恰当地传达问题的严重性,打电话的人可能会错误地试图抓住和处理这个案件。事实上,如果这一行曾经到达,所讨论的程序将被破坏,唯一明智的做法是退出这里的要点是,enum有一组有限的值,因此不可能到达
throw
行-只有当enum的定义发生了更改而没有修复此实例方法时,才会发生这种情况。抛出RuntimeException
表明调用方犯了错误,而实际上方法(和枚举)本身已经损坏。显式地引发AssertionError
正确地表示该方法期望的不变量已被违反番石榴有一篇有用的文章,它把when to raise different types of exceptions分解了。他们写道:
该网页说} 类中的注释还提供了一些关于选择异常的有用见解。在
AssertionError
是处理这些案件的推荐方法。他们的^{AssertionError
似乎太强的情况下,提出VerifyException
可能是一个很好的折衷方案至于
Error
或RuntimeException
的具体问题,这其实并不重要(两者都是未检查的,因此可能会沿着调用堆栈向上移动而不会被捕获),但调用方更有可能尝试从RuntimeException
恢复。在这种情况下使应用程序崩溃是一个功能,因为否则我们将继续运行(此时)明显不正确的应用程序。当然,调用方捕获和处理AssertionError
(或Error
或Throwable
)的可能性较小,但是调用方当然可以做任何他们想做的事情# 5 楼答案
在我看来,在这里使用
AssertionError
是不正确的From the docs,断言错误扩展基类^{}
错误应该是致命的,而我希望您的程序能够处理此错误,并向用户显示有关未知操作的警告消息
如果这里有什么问题的话,我希望抛出一个^{} ,并在调用堆栈中的其他地方进行处理
考虑不使用计算器的情况,而是使用EnNS:
的任何代码流。如果开发人员要向现有枚举添加新值,我不希望使用此现有枚举的函数调用错误,因为新值不受支持
# 6 楼答案
关于错误Java Tutorial指出:
此外,《指南》规定:
所以我认为例外是检查这种情况的正确方法
我建议使用
new UnsupportedOperationException("Operator " + name() + " is not supported.");
,因为我认为它可以更好地描述问题(即开发人员添加了一个enum值,但忘记实现所需的案例)然而,我认为这个示例案例应该使用
AbstractEnum
设计模式,而不是开关:它不太容易出错,因为在每个案例都实现
apply
之前,此代码不会编译